package com.bst.etl.service.impl;

import com.alibaba.druid.pool.DruidDataSource;
import com.bst.base.service.IBaseDimCompResultService;
import com.bst.base.service.IBaseDimCompService;
import com.bst.common.base.service.IBaseDWService;
import com.bst.common.core.domain.AjaxResult;
import com.bst.common.utils.StringUtils;
import com.bst.common.vo.HeaderAndBodyVO;
import com.bst.etl.service.IEtlQryDwPubService;
import com.bst.common.vo.DimVO;
import com.bst.common.vo.DwQueryParamVO;
import com.bst.etl.vo.EtlDrawDmExtVO;
import com.bst.md.domain.MdMedDim;
import com.bst.md.domain.MdMedPubfld;
import com.bst.md.domain.MdMedTbFld;
import com.bst.md.service.IMdMedDimService;
import com.bst.md.service.IMdMedPubfldService;
import com.bst.md.service.IMdMedTbFldService;
import com.bst.md.service.IMdMedTbService;
import com.bst.system.framework.datasource.DynamicDataSource;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class EtlQryDwPubServiceImpl implements IEtlQryDwPubService {

    private static final String COMP_UNIQUE_KEY="UNIQUE_KEY";

    @Autowired
    IMdMedTbService mdMedTbService;
    @Autowired
    IMdMedTbFldService mdMedTbFldService;
    @Autowired
    IMdMedPubfldService mdMedPubfldService;
    @Autowired
    IBaseDWService baseDWService;
    @Autowired
    IBaseDimCompResultService dimCompResultService;
    @Autowired
    IBaseDimCompService dimCompService;
    @Autowired
    IMdMedDimService mdMedDimService;

    @Override
    public List<Map<String,Object>> findIndexData(DwQueryParamVO paramVO) {
        DruidDataSource datasource_dw = (DruidDataSource) DynamicDataSource.getDataSourceMap().get("dw");
        paramVO.setDbType(datasource_dw.getDbType());
        fldHandler(paramVO);
        List<Map<String,Object>> data = baseDWService.selectCommonDwData(paramVO);
        return data;
    }

    @Override
    public AjaxResult findIndexDataWithHeader(DwQueryParamVO paramVO) {
        List<Map<String,Object>> data;
        DruidDataSource datasource_dw = (DruidDataSource) DynamicDataSource.getDataSourceMap().get("dw");
        paramVO.setDbType(datasource_dw.getDbType());
        fldHandler(paramVO);
        data = baseDWService.selectCommonDwData(paramVO);
        HeaderAndBodyVO dataVO = new HeaderAndBodyVO();
        dataVO.setTbody(data);
        Map<String,String> headerMap = null;
        if(data==null || data.size()==0) {
            headerMap = new HashMap<>();
        } else {
            headerMap = queryHeaders(data.get(0),paramVO);
        }
        dataVO.setThead(headerMap);
        return AjaxResult.success(dataVO);
    }

    private void fldHandler(DwQueryParamVO paramVO) {
        Boolean fgDetail = paramVO.getFgDetail();
        List<DimVO> dimVOS = paramVO.getDimVOList();
        int dimNum = 0;
        List<MdMedDim> dims = null;
        Map<String,MdMedDim> dimMap = null;
        MdMedDim medDim;
        String dimAlias,idPubfld,naPubFld,filter,whereSql="";
        MdMedPubfld pubfld = new MdMedPubfld();
        pubfld.setNa("ID_DIM_");
        List<MdMedPubfld> dimPubFld = null;
        Map<String,MdMedPubfld> pubFldMap = null;
        List<DimVO> newDimVOs = new ArrayList<>();
        for (DimVO dimVO : dimVOS) {
            newDimVOs.add(dimVO);
            List<String> otherFlds = dimVO.getOtherFlds();
            filter = dimVO.getFilter();
            if(StringUtils.isNotEmpty(filter)) {
                if(filter.startsWith("ID_") || filter.startsWith("NA_")) {
                    whereSql += dimVO.getFilter();
                }
            }
            if(otherFlds!=null && otherFlds.size()>0 ) { //字典的其他字段显示
                idPubfld = dimVO.getIdPubfld();
                if(dims==null) {
                    dims = mdMedDimService.selectMdMedDimList(new MdMedDim());
                    dimMap = dims.stream().collect(Collectors.toMap(MdMedDim::getCdTb, e->e));
                    dimPubFld = mdMedPubfldService.selectMdMedPubfldList(pubfld);
                    pubFldMap = dimPubFld.stream().collect(Collectors.toMap(MdMedPubfld::getIdPubfld, e->e));
                }
                pubfld = pubFldMap.get(idPubfld);
                medDim = dimMap.get(pubFldMap.get(idPubfld).getCdTbDim().toUpperCase());
                if(medDim!=null) {
                    medDim = dimMap.get(pubfld.getCdTbDim().toUpperCase());
                    Map<String,String> dimFldMap = new HashMap<>();
                    dimAlias = "dim"+(++dimNum);
                    for (String dimFld : medDim.getFlds().split(",")) {
                        dimFldMap.put(dimFld.split(":")[0],dimFld.split(":")[1]);
                    }
                    List<DimVO> otherDimVOList = new ArrayList<>();
                    paramVO.getOtherDimVOMap().put(idPubfld,otherDimVOList);
                    for (String otherFld : otherFlds) {
                        DimVO dimVO1 = new DimVO();
                        /*if("BIRTHDAY".equals(otherFld.toUpperCase())) {
                            dimVO1.setIdPubfld("CONVERT(nvarchar, "+dimAlias+"."+otherFld.toUpperCase()+",23)");
                        } else {
                            dimVO1.setIdPubfld(dimAlias+"."+otherFld.toUpperCase());
                        }*/
                        dimVO1.setIdPubfld(dimAlias+"."+otherFld.toUpperCase());
                        dimVO1.setNaPubfld(dimFldMap.get(otherFld.toUpperCase()));
                        dimVO1.setAlias(otherFld.toUpperCase());
                        otherDimVOList.add(dimVO1);
                        newDimVOs.add(dimVO1);
                    }
                    paramVO.setJoinTables(paramVO.getJoinTables()+" left join "+pubFldMap.get(idPubfld).getCdTbDim()+" as "+dimAlias+" on dw."+idPubfld+"="+dimAlias+"."+medDim.getCdFld());
                }
            }
            //
        }
        paramVO.setDimVOList(newDimVOs);
        if(!fgDetail) {
            Map<String,DimVO> newDimVOMap = new LinkedHashMap<>();
            String groupBy="";
            MdMedTbFld fld = new MdMedTbFld();
            fld.setCdTb(paramVO.getTableName());
            List<MdMedTbFld> allFlds = mdMedTbFldService.selectMdMedTbFldList(fld);
            Map<String,MdMedTbFld> fldMap = allFlds.stream().collect(Collectors.toMap(MdMedTbFld::getIdPubfld, e->e));
            for (DimVO dimVO : dimVOS) {
                idPubfld = dimVO.getIdPubfld();
                if(idPubfld.startsWith("ID_DIM_")) {
                    groupBy += idPubfld+",";
                    naPubFld = idPubfld.replace("ID_","NA_");
                    fld = fldMap.get(idPubfld);
                    if(fldMap.keySet().contains(naPubFld)) {
                        newDimVOMap.put(naPubFld,new DimVO(naPubFld,null));
                        if(!groupBy.contains(naPubFld)) {
                            groupBy += naPubFld+",";
                        }
                    }
                }
                newDimVOMap.put(idPubfld,dimVO);
            }
            if(groupBy.length()>0) {
                paramVO.setGroupBy(groupBy.substring(0,groupBy.length()-1));
            }
            dimVOS = new ArrayList<>(newDimVOMap.values());
            paramVO.setOrderBy(null);
            paramVO.setDimVOList(dimVOS);
        }
        if(StringUtils.isEmpty(paramVO.getWhereSql())) {
            paramVO.setWhereSql(whereSql);
        } else {
            paramVO.setWhereSql(paramVO.getWhereSql()+(whereSql==""?"":" and "+whereSql));
        }

    }

    private Map<String,String> queryHeaders(Map<String,Object> data,DwQueryParamVO paramVO) {
        Map<String,String> headerNameMap = new LinkedHashMap<>();
        Map<String,List<DimVO>> otherDimVOMap = paramVO.getOtherDimVOMap();
        List<DimVO> dimVOS = paramVO.getDimVOList();
        List<String> showFlds = new ArrayList<>();
        for (DimVO dimVO : dimVOS) {
            if(dimVO.getFgHide()==0) {
                showFlds.add(dimVO.getIdPubfld());
            }
        }
        //if(data!=null) {
            List<MdMedPubfld> pubflds = mdMedPubfldService.findByIdList(showFlds);
            Map<String,MdMedPubfld> pubfldMap =pubflds.stream().collect(Collectors.toMap(MdMedPubfld::getIdPubfld, e->e));
            String key;
            for (DimVO dimVO : dimVOS) {
                key = dimVO.getAlias()==null?dimVO.getIdPubfld():dimVO.getAlias();
                headerNameMap.put(key,StringUtils.isNotEmpty(dimVO.getNaPubfld())?dimVO.getNaPubfld():(pubfldMap.get(key)==null?key:pubfldMap.get(key).getNa()));
            }
        //}
        return headerNameMap;
    }
}
